/** @file    ContactInfo.cpp
 *  @author  Alessandro Polo
 *  @version $Id: ContactInfo.cpp 2877 2010-08-09 00:02:53Z alex $
 *  @brief
 * File containing methods for the wosh::communication::ContactInfo class.
 * The header for this class can be found in ContactInfo.h, check that file
 * for class description.
 ****************************************************************************/
/* Copyright (c) 2007-2010, WOSH - Wide Open Smart Home 
 * by Alessandro Polo - OpenSmartHome.com
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are met:
 *     * Redistributions of source code must retain the above copyright
 *       notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above copyright
 *       notice, this list of conditions and the following disclaimer in the
 *       documentation and/or other materials provided with the distribution.
 *     * Neither the name of the OpenSmartHome.com WOSH nor the
 *       names of its contributors may be used to endorse or promote products
 *       derived from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY Alessandro Polo ''AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL Alessandro Polo BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 ****************************************************************************/
 
 #include <framework/communication/ContactInfo.h>

 #include <core/ObjectAllocator.h>
 #include <core/Utilities.h>
 #include <core/DataModels.h>


using namespace std;
namespace wosh {
 namespace communication {

 WOSH_REGISTER(wosh::communication::ContactInfo, "wosh::ISerializable", 1.0, _static_ContactInfo )

//////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS

ContactInfo::ContactInfo() {
	clear();
 }

ContactInfo::ContactInfo( const ContactInfo& m ) {
	*this = m;
 }

//////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

void ContactInfo::clear() {
	this->userID = "";
	this->userWosh = "";
	this->lastSeen = 0;
	this->statusMsg = "";
	this->presence = User::PRESENCE_UNKNOWN;
	this->status = User::STATUS_UNKNOWN;
	this->protocol = Notification::PROTOCOL_UNKNOWN;
	this->language = "";
	this->lastTargetWoshUser = "";
	this->session = NULL;
 }

void ContactInfo::set( const std::string& custom_user, const std::string& wosh_user, long last_seen ) {
	this->userID = custom_user;
	this->userWosh = wosh_user;
	this->lastSeen = last_seen;
 }

void ContactInfo::setLastSeen() {
	this->lastSeen = Utilities::std_time();
 }
bool ContactInfo::isTimedOut( long seconds ) const {
	return ( this->lastSeen < 0 || (long)Utilities::std_time() - this->lastSeen > seconds );
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

ContactInfo& ContactInfo::operator=(const ContactInfo& m) {
	this->userID = m.userID;
	this->userWosh = m.userWosh;
	this->lastSeen = m.lastSeen;
	this->statusMsg = m.statusMsg;
	this->presence = m.presence;
	this->status = m.status;
	this->protocol = m.protocol;
	this->language = m.language;
	this->lastTargetWoshUser = m.lastTargetWoshUser;
	return *this;
 }

bool ContactInfo::operator==(const ContactInfo &other) const {
	if ( this->userID != other.userID )
		return false;
	if ( this->userWosh != other.userWosh )
		return false;
	if ( this->lastSeen != other.lastSeen )
		return false;
	return true;
 }

//////////////////////////////////////////////////////////////////////////////////////////////// DEBUG & INFO
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

std::string ContactInfo::toString() const {
	return Utilities::format("%s[%s]@%ld", this->userID.c_str(), this->userWosh.c_str(), this->lastSeen );
 }

bool ContactInfo::updateHash( DataHashContext* hash_context ) const {
	if ( hash_context == NULL ) return false;
	bool ret = true;
	ret = hash_context->update( this->userID ) & ret;
	ret = hash_context->update( this->userWosh ) & ret;
	ret = hash_context->update( this->lastSeen ) & ret;
	ret = hash_context->update( this->protocol ) & ret;
	ret = hash_context->update( this->language ) & ret;
	ret = hash_context->update( this->lastTargetWoshUser ) & ret;
	return ret;
 }

/////////////////////////////////////////////////////////////////////////////////////////////// SERIALIZATION
//////////////////////////////////////////////////////////////////////////////////////////////////////////////

DataFieldCollector<ContactInfo>* ContactInfo::getDataFields() {
	DataFieldCollector<ContactInfo>* fields = new DataFieldCollector<ContactInfo>();
	fields->add<const std::string&, Variant>(&ContactInfo::getUserID, "Account", 0);
	fields->add<const std::string&, Variant>(&ContactInfo::getUser, "User", 1);
	fields->add<long,Variant_DT>(&ContactInfo::getLastSeen, "LastSeen", 2);
	fields->add<const char*,Variant>(&ContactInfo::getUserPresenceAsString, "Presence", 3);
	fields->add<const char*,Variant>(&ContactInfo::getUserStatusAsString, "Status", 4);
	fields->add<const std::string&,Variant>(&ContactInfo::getStatusMessage, "StatusMessage", 5);
	fields->add<const std::string&, Variant>(&ContactInfo::getLanguage, "Language", 6);
	fields->add<const std::string&, Variant>(&ContactInfo::getLastTargetUser, "LastTargetUser", 7);
	fields->add<Notification::PROTOCOL,Variant>(&ContactInfo::getProtocol, "Protocol", 8, false);
	fields->add<bool,Variant>(&ContactInfo::isOnline, "isOnline", 9, false);
	fields->add<bool,Variant>(&ContactInfo::isOffline, "isOffline", 10, false);
	return fields;
 }

//////////////////////////////////////////////////////////////////////////////////////////////////////////////

 }; // namespace communication
}; // namespace wosh
